package hystrix;

import com.netflix.hystrix.HystrixCollapser;
import com.netflix.hystrix.HystrixCommand;
import rest.entity.User;

import java.util.Collection;
import java.util.Map;

/**
 * 合并处理器
 * 注意被继承的HystrixCollapser有三个参数类型，
 * 第一个参数类型：批处理返回的结果类型，就是CollapserUserCommand的返回类型
 * 第二个参数类型：单次请求的返回结果类型，这里单次请求是传入userId，获取user，所以第二个参数类型应该是User
 * 第三个参数类型：请求的参数类型If multiple arguments are needed, wrap them in another object or a Tuple
 */
public class SingleUserCommand extends HystrixCollapser<Map<String,User>,User,String> {
    String userId;
    static String url = "http://localhost:9100";

    public SingleUserCommand(String userId){
        this.userId = userId;
    }

    public static void setUrl(String newurl){
        url = newurl;
    }
    /**
     * The request arguments to be passed to the {@link HystrixCommand}.
     * <p>
     * Typically this means to take the argument(s) provided to the constructor and return it here.
     * <p>
     * If there are multiple arguments that need to be bundled, create a single object to contain them, or use a Tuple.
     *
     * @return RequestArgumentType
     */
    public String getRequestArgument() {
        return userId;
    }

    /**
     * Factory method to create a new {@link HystrixCommand}{@code <BatchReturnType>} command object each time a batch needs to be executed.
     * <p>
     * Do not return the same instance each time. Return a new instance on each invocation.
     * <p>
     * Process the 'requests' argument into the arguments the command object needs to perform its work.
     * <p>
     * If a batch or requests needs to be split (sharded) into multiple commands, see {@link #shardRequests} <p>
     * IMPLEMENTATION NOTE: Be fast (ie. <1ms) in this method otherwise it can block the Timer from executing subsequent batches. Do not do any processing beyond constructing the command and returning
     * it.
     *
     * @param collapsedRequests {@code Collection<CollapsedRequest<ResponseType, RequestArgumentType>>} containing {@link CollapsedRequest} objects containing the arguments of each request collapsed in this batch.
     * @return {@link HystrixCommand}{@code <BatchReturnType>} which when executed will retrieve results for the batch of arguments as found in the Collection of {@link CollapsedRequest} objects
     */
    protected HystrixCommand<Map<String, User>> createCommand(Collection<CollapsedRequest<User, String>> collapsedRequests) {
        CollapserUserCommand collapserUserCommand = new CollapserUserCommand(collapsedRequests, url);
        return collapserUserCommand;
    }




    /**
     * Executed after the {@link HystrixCommand}{@code <BatchReturnType>} command created by {@link #createCommand} finishes processing (unless it fails) for mapping the {@code <BatchReturnType>} to
     * the list of {@code CollapsedRequest<ResponseType, RequestArgumentType>} objects.
     * <p>
     * IMPORTANT IMPLEMENTATION DETAIL => The expected contract (responsibilities) of this method implementation is:
     * <p>
     * <ul>
     * <li>ALL {@link CollapsedRequest} objects must have either a response or exception set on them even if the response is NULL
     * otherwise the user thread waiting on the response will think a response was never received and will either block indefinitely or timeout while waiting.</li>
     * <ul>
     * <li>Setting a response is done via {@link CollapsedRequest#setResponse(Object)}</li>
     * <li>Setting an exception is done via {@link CollapsedRequest#setException(Exception)}</li>
     * </ul>
     * </ul>
     * <p>
     * Common code when {@code <BatchReturnType>} is {@code List<ResponseType>} is:
     * <p>
     * <p>
     * <pre>
     * int count = 0;
     * for ({@code CollapsedRequest<ResponseType, RequestArgumentType>} request : requests) {
     * &nbsp;&nbsp;&nbsp;&nbsp; request.setResponse(batchResponse.get(count++));
     * }
     * </pre>
     * <p>
     * For example if the types were {@code <List<String>, String, String>}:
     * <p>
     * <p>
     * <pre>
     * int count = 0;
     * for ({@code CollapsedRequest<String, String>} request : requests) {
     * &nbsp;&nbsp;&nbsp;&nbsp; request.setResponse(batchResponse.get(count++));
     * }
     * </pre>
     *
     * @param batchResponse     The {@code <BatchReturnType>} returned from the {@link HystrixCommand}{@code <BatchReturnType>} command created by {@link #createCommand}.
     *                          <p>
     * @param collapsedRequests {@code Collection<CollapsedRequest<ResponseType, RequestArgumentType>>} containing {@link CollapsedRequest} objects containing the arguments of each request collapsed in this batch.
     *                          <p>
     *                          The {@link CollapsedRequest#setResponse(Object)} or {@link CollapsedRequest#setException(Exception)} must be called on each {@link CollapsedRequest} in the Collection.
     */
    protected void mapResponseToRequests(Map<String, User> batchResponse, Collection<CollapsedRequest<User, String>> collapsedRequests) {
        //匹配关联和结果
        for (CollapsedRequest<User, String> request : collapsedRequests) {
            String id = request.getArgument();
            User user = batchResponse.get(id);
            request.setResponse(user);
        }
    }
}
